#pragma once

#include "IRegion.h"
#include "Types.h"
#include <vgraph>

template<typename T>
class Region : public DataEntity<T>
{
public:
	BEGIN_DEFINE_CLASS(CLASSID_NULL)
		USE_INTERFACE_ENTRY(DataEntity)
		DEFINE_INTERFACE_ENTRY(IRegion)
	END_DEFINE_CLASS()

	Region()
	{	
		m_category = unknownRegion;
	}
	virtual ~Region(){}

	virtual void AddPoint(const Point& pt);
	virtual void InsertPoint(int32 index,const Point& pt);
	virtual void AddLine(const Point& begin,const Point& end);
	virtual void AddRectangle(const Point& lefttop,const Point& rightbottom);

	virtual const Point& GetPoint(uint32 index) const;
	virtual uint32 CountPoint() const;
	virtual bool ContainPoint(const Point& pt) const;
	virtual regionCategory GetCategory() const;
	virtual void SetCategory(regionCategory value){m_category = value;}

protected:
	virtual void SetPoint(uint32 index,const Point& pt);

private:
	regionCategory m_category;
	Points m_points;
};

//////////////////////////////////////////////////////////////////////////
//inline
template<typename T>
void Region<T>::AddPoint(const Point& pt)
{
	m_points.push_back(pt);
}

template<typename T>
void Region<T>::InsertPoint(int32 index,const Point& pt)
{
	if (index == -1)
		m_points.push_back(pt);
	else if (m_points.empty())
		m_points.push_back(pt);
	else
	{
		m_points.insert(m_points.begin()+index,pt);
	}
}

template<typename T>
void Region<T>::AddLine(const Point& begin,const Point& end)
{
	m_points.push_back(begin);
	m_points.push_back(end);
}

template<typename T>
void Region<T>::AddRectangle(const Point& lefttop,const Point& rightbottom)
{
	m_points.push_back(lefttop);
	m_points.push_back(rightbottom);
}

template<typename T>
void Region<T>::SetPoint(uint32 index,const Point& pt)
{
	ASSERT(index < m_points.size());

	Points::iterator it = m_points.begin();
	std::advance(it,index);
	*it = pt;
}

template<typename T>
inline const Point& Region<T>::GetPoint(uint32 index) const
{
	ASSERT(index < m_points.size());
	return m_points[index];
}

template<typename T>
inline uint32 Region<T>::CountPoint() const
{
	return m_points.size();
}

template<typename T>
inline bool Region<T>::ContainPoint(const Point& pt) const 
{
	Points::const_iterator itfind = std::find(m_points.begin(),m_points.end(),pt);
	return (itfind != m_points.end());
}

template<typename T>
inline regionCategory Region<T>::GetCategory() const
{
	return m_category;
}